Using Go's Variable Types

Get introduced to Go's variable types and learn how to declare them.

Modern programming languages are built with primitives called types. When we hear that a variable is a string or integer, we are talking about the variable’s type. With today’s programming languages, there are two common type systems used:

  • Dynamic types (also called duck typing)

  • Static types

svg viewer

Go is a statically typed language. For those who might be coming from languages such as Python, Perl, and PHP, then those languages are dynamically typed. In a dynamically typed language, we can create a variable and store anything in it. In those languages, the type simply indicates what is stored in the variable. Here is an example in Python:

Variables in Python

In this case, v can store anything, and the type held by v is unknown without using some runtime checks (runtime meaning that it can't be checked at compile time). In a statically typed language, the type of the variable is set when it is created. That type cannot change. In this type of language, the type is both what is stored in the variable and what can be stored in the variable. Here is a Go example:

Static variables in Go

The v value cannot be set to any other type than a string. It might seem like Python is superior because it can store anything in its variable. But in practice, this lack of being specific means that Python must wait until a program is running before it can find out there is a problem (what we call a runtime error). It is better to find the problem when the software is compiled than when it is deployed. Let's take a look at a function to add two numbers together as an example. Here is the Python version:

Python function to add two numbers

Here is the Go version:

Go function to add two numbers

In the Python version, we can see that a and b will be added together. But what types are a and b? What is the result type? What happens if we pass an integer and a float or an integer and a string? In some cases, two types cannot be added together in Python, which will cause a runtime exception, and we can never be sure of what the result type will be.

Note: Python has added type hints to the language to help avoid these problems. But, practical experience has taught us with JavaScript, Dart, TypeScript, and Closure that while it can help, optional type support means that a lot of problems fall through the cracks.

Our Go version defines the exact types of our arguments and our result. We cannot pass an integer and a float or an integer and a string. We'll only ever receive an integer as a return. This allows our compiler to find any errors with variable types when the program is compiled. In Python, this error could show up at any time, from the instant it ran to 6 months later when a certain code path was executed.

Note: A few years ago, there was a study done on the Rosetta Code repository for some of the top languages in use to see how they fared in processing time, memory use, and runtime failures. For runtime failures, Go had the least failures, with Python towards the bottom of the ranking. Static typing would have certainly played into that.

Go's types#

Go has a rich type system that not only specifies that a type might be an integer but also the size of the integer. This allows a Go programmer to reduce the size of a variable both in memory and when encoding for network transport. The following table shows the most common types used in Go:

Common Go types

Type

Description

int

A 64-bit signed integer on 64-bit systems, 32 on 32-bit systems

bool

A Boolean, either true or false

string

A string of UTF-8 characters

float64

A 64-bit floating-point number

slice

A growable list of items

map

Key-value pairs, similar to Python's dictionaries

struct

A collection of named attributes (variables), similar to Python objects

interface

A type that holds a value with specifically defined methods

pointers

A type that stores the memory address of a variable, not the variable

channels

A buffered or non-buffered pipe for sending data asynchronously

We’ll be keeping our discussion mostly to the preceding types; here is the full list

Go doesn't just provide these types; we can also create new types based on these basic types. These custom types become their own type and can have methods attached to them. Declaring a custom type is done with the type keyword and will be discussed during the lesson on the struct type. For now, we are going to move on to the basics of declaring variables. Now that we've talked about our variable types, let's have a look at how we can create them.

Declaring variables#

As in most languages, declaring a variable allocates storage that will hold some type of data. In Go, that data is typed so that only that type can be stored in the allocated storage. As Go has multiple ways to declare a variable, the next parts will talk about the different ways this can be done.

The long way to declare a variable#

The most specific way to declare a variable is using the var keyword. We can use var to declare a variable both at the package level (meaning not inside a function) and within a function. Let's look at some examples of ways to declare variables using var:

Variable declaration of type int64

This declares an i variable that can hold an int64 type. No value is assigned, so the value is assigned the zero value of an integer, which is 0:

Variable declaration and value assignment

This declares an i variable that can hold an int type. The value 3 is assigned to i. Note that the int and int64 types are distinct. We cannot use an int type as an int64 type, and vice versa. However, we can do type conversions to allow interchanging these types:

Variable group declaration

Using (), we group together a set of declarations. i can hold an int type and has the integer zero value, 0. word doesn't declare the type, but it is inferred by the string value on the right side of the equal (=) operator.

The shorter way#

In the previous example, we used the var keyword to create a variable and the = operator to assign values. If we do not have an = operator, the compiler assigns the zero value for the type (more on this later). The important concept is as follows:

  • var created the variable but did not make an assignment.

  • The equal (=) operator assigned a value to the variable.

Within a function (not at the package level), we can do a create and assign by using the := operator. This both creates a new variable and assigns a value to it:

Variable declaration

The important thing to remember when using := is that it means to create and assign. If the variable already exists, we cannot use :=, but must use =, which just does an assignment.

Utilizing Go Packages

Variable Scopes and Shadowing